/*
 * Copyright 2019, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.example.android.marsrealestate.overview

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.android.marsrealestate.databinding.GridViewItemBinding
import com.example.android.marsrealestate.network.Activity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

private val ITEM_VIEW_TYPE_HEADER = 0
private val ITEM_VIEW_TYPE_ITEM = 1

class PhotoGridAdapter(val clickListener: ActivityListener) :
        ListAdapter<DataItem, RecyclerView.ViewHolder>(PhotoGridAdapterDiffCallback()) {

    /** 使用协程 */
    private val adapterScope = CoroutineScope(Dispatchers.Default)

    class PhotoGridAdapterDiffCallback : DiffUtil.ItemCallback<DataItem>() {
        override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
            return oldItem == newItem
        }
    }

    // 第一步，使用binding class作为root layout
    // 更改ViewHolder类的签名，以便构造函数是私有的 private constructor
    class ActivityViewHolder private constructor(val binding: GridViewItemBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Activity?, clickListener: ActivityListener) {
            binding.activity = item
            // binding.viewModel.activity = item
            binding.clickListener = clickListener
            binding.executePendingBindings()
        }

        companion object {
            fun from(parent: ViewGroup): ActivityViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val binding = GridViewItemBinding.inflate(layoutInflater, parent, false)

                return ActivityViewHolder(binding)
            }
        }
    }

    // 第二步，inflate内容并返回ActivityViewHolder
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
//        return when (viewType) {
//            ITEM_VIEW_TYPE_ITEM -> ActivityViewHolder.from(parent)
//            else -> throw ClassCastException("Unknown viewType $viewType")
//        }
        return ActivityViewHolder.from(parent)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ActivityViewHolder -> {
                val activityItem = getItem(position) as DataItem.ActivityItem
                holder.bind(activityItem.activity, clickListener)
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        //        return when (getItem(position)) {
        //            is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
        //            is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
        //        }
        return ITEM_VIEW_TYPE_ITEM
    }

    /**
     * 启动协程adapterScope以操作列表
     * 切换到Dispatchers.Main上下文以提交列表
     */
    fun addHeaderAndSubmitList(list: List<Activity>) {
        adapterScope.launch {
            val items = when (list) {
                null -> listOf(null)
                else -> list.map { DataItem.ActivityItem(it) }
            }
            withContext(Dispatchers.Main) {
                submitList(items)
            }
        }
    }

}

/**
 * 点击监听
 */
class ActivityListener(val clickListener: (activityId: String) -> Unit) {
    fun onClick(activity: Activity) = activity.activityId?.let { clickListener(it) };
}

/**
 * sealed定义了一个封闭的类型
 */
sealed class DataItem {
    /**
     * 当适配器用于DiffUtil确定某个项目是否以及如何更改时，DiffItemCallback需要知道每个项目的ID
     */
    abstract val id: String?

    data class ActivityItem(val activity: Activity) : DataItem() {
        override val id: String?
            get() = activity.activityId
    }
}